﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace Tzync
{
    //resolve conflicts screen
    public partial class ConflictUIForm : Form
    {
        private SyncTool syncTool;
        private List<Difference> conflictList;  //list of conflicts found
        private int noOfConflictsLeft;  //no of conflicts left unresolved
        private bool selectAll; //toggle select/de-select of conflicts

        public ConflictUIForm(SyncTool newSyncTool, List<Difference> newConflictList)
        {
            //initialization
            this.syncTool = newSyncTool;
            this.conflictList = newConflictList;
            this.noOfConflictsLeft = newConflictList.Count;
            InitializeComponent();
        }

        private void ResolveConflictUI_Load(object sender, EventArgs e)
        {
            //defaults
            infoLabel.Text = "";
            conflictComboBox.SelectedIndex = 0;

            //tooltips
            applyToolTip.SetToolTip(applyBtn, "Click here to apply the chosen sync direction to selected files");
            selectBtnToolTip.SetToolTip(selectAllBtn, "Click here to select or de-select all conflicts");
            
            DisplayConflicts();
        }

        //displays conflicts found in UI
        public void DisplayConflicts()
        {
            infoLabel.Text = "";
            conflictLV.Items.Clear();
            TreeNode tNode = new TreeNode();
            ListViewItem items;
            Type typeOfConflict;
            Pair<DirectionType, OperationType> conflictDetails;
            bool toAdd = false;

            foreach (Difference conflictFound in conflictList)
            {
                items = new ListViewItem();
                typeOfConflict = conflictFound.GetItemType();
                conflictDetails = conflictFound.GetPairType();
                toAdd = AddConflict(items, typeOfConflict, conflictDetails, tNode, conflictFound);

                if (toAdd)
                    conflictLV.Items.Add(items);
            }

            ResizeColumns();
        }

        //displays conflicts found
        private bool AddConflict(ListViewItem items, Type typeOfConflict, Pair<DirectionType, OperationType> conflictDetails, TreeNode tNode, Difference conflictFound)
        {
            infoLabel.Text = "";
            if (typeOfConflict == Type.File)    //file
            {
                FileInfo fileInfo = conflictFound.GetSysFile();
                tNode = conflictFound.GetPartnerFile();

                if (syncTool.GetSystemName() == SystemType.Host)    //A
                {
                    items.Text = tNode.getFullPathA(); //path of file
                    items.SubItems.Add("" + tNode.getSyncA());  //last modified date of file
                }
                else if (syncTool.GetSystemName() == SystemType.Guest)  //B
                {
                    items.Text = tNode.getFullPathB(); //path of file 
                    items.SubItems.Add("" + tNode.getSyncB());  //last modified date of file
                }

                //displays action taken
                if (conflictDetails.Second == OperationType.CreationCreationConflict)
                    items.SubItems.Add("Conflict - file created on both computers");
                else if (conflictDetails.Second == OperationType.ModDeleteConflict)
                    items.SubItems.Add("Conflict - file modified on 1 computer and deleted on the other");
                else if (conflictDetails.Second == OperationType.ModModConflict)
                    items.SubItems.Add("Conflict - file modified on both computers");
                else if (conflictDetails.Second == OperationType.DeletionDeletionConflict)
                    items.SubItems.Add("Conflict - file deleted on both computers");

                items.SubItems.Add("To be resolved");     //direction of sync
                items.ForeColor = Color.Red;

                return true;
            }

            else if (typeOfConflict == Type.Folder) //folder
            {
                //ignore del-del, mod-mod and creation-creation folder conflicts
                if (conflictDetails.Second != OperationType.DeletionDeletionConflict
                && conflictDetails.Second != OperationType.ModModConflict && conflictDetails.Second != OperationType.CreationCreationConflict)
                {
                    DirectoryInfo dirInfo = conflictFound.GetSysFolder();
                    tNode = conflictFound.GetPartnerFolder();

                    if (syncTool.GetSystemName() == SystemType.Host)    //A
                    {
                        items.Text = tNode.getFullPathA(); //path of folder  
                        items.SubItems.Add("" + tNode.getSyncA());  //last modified date of folder
                    }
                    else if (syncTool.GetSystemName() == SystemType.Guest)  //B
                    {
                        items.Text = tNode.getFullPathB(); //path of folder  
                        items.SubItems.Add("" + tNode.getSyncB());  //last modified date of folder
                    }

                    //displays action taken
                    if (conflictDetails.Second == OperationType.ModDeleteConflict)
                        items.SubItems.Add("Conflict - folder modified on 1 computer and deleted on the other");
                    else if (conflictDetails.Second == OperationType.CreationCreationConflict)
                        items.SubItems.Add("Conflict - folder created on both computers");
                    else if (conflictDetails.Second == OperationType.DeletionDeletionConflict)
                        items.SubItems.Add("Conflict - folder deleted on both computers");

                    items.SubItems.Add("To be resolved");     //direction of sync
                    items.ForeColor = Color.Red;

                    return true;
                }
            }

            return false;
        }

        private void conflictListView_ItemChecked(object sender, ItemCheckedEventArgs e)
        {
            infoLabel.Text = "";
        }

        private void applyBtn_Click(object sender, EventArgs e)
        {
            infoLabel.Text = "";
            if (conflictLV.CheckedItems.Count <= 0)
            {
                infoLabel.Text = "No conflicts have been selected!";
                return;
            }
            
            Difference conflictFound;
            List<Difference> resolvedConflictList = new List<Difference>();
            
            foreach (ListViewItem item in conflictLV.CheckedItems)
            {
                conflictFound = conflictList[item.Index];   //gets checked conflict
                
                //resolve sync direction
                if (conflictComboBox.SelectedIndex == 0)
                    conflictFound.SetPairType(new Pair<DirectionType, OperationType>(DirectionType.SystemToHD, conflictFound.GetPairType().Second));
                else if (conflictComboBox.SelectedIndex == 1)
                    conflictFound.SetPairType(new Pair<DirectionType, OperationType>(DirectionType.HDToSystem, conflictFound.GetPairType().Second));
                noOfConflictsLeft--;
                
                conflictLV.Items.Remove(item);    //remove resolved item from display
                resolvedConflictList.Add(conflictFound);  //Add to the another copy
                conflictList.Remove(conflictFound);       //Remove from conflictList so that index is updated for next iteration 
            }

            infoLabel.Text = "Resolving in progress...";
            Cursor.Current = Cursors.WaitCursor;            
            syncTool.ResolveConflicts(resolvedConflictList);    //resolves conflicts
            Cursor.Current = Cursors.Default;
            infoLabel.Text = "Conflicts Resolved!";

            if (noOfConflictsLeft == 0)    //closes form automatically when conflicts are all resolved
                this.Close();
            else
                return;
        }

        //user must resolve all conflicts before proceeding
        private void ResolveConflictUIForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            infoLabel.Text = "";
            if (noOfConflictsLeft > 0)  //check if all conflicts have been resolved
            {
                infoLabel.Text = "Please resolve all conflicts before exiting!";
                e.Cancel = true;
            }

            this.DialogResult = DialogResult.OK;
        }

        private void selectAllBtn_Click(object sender, EventArgs e)
        {
            if (conflictLV.Items.Count > 0)
            {
                if (!selectAll)
                {
                    foreach (ListViewItem item in conflictLV.Items)
                        item.Checked = true;
                    selectAll = true;
                }
                else
                {
                    foreach (ListViewItem item in conflictLV.Items)
                        item.Checked = false;
                    selectAll = false;
                }
            }
        }

        //function to auto resize columns
        private void ResizeColumns()
        {
            int contentWidth, headerWidth;
            ColumnHeaderAutoResizeStyle headerResize;

            for (int index = 0; index < conflictLV.Columns.Count; index++)
            {
                ColumnHeader header = conflictLV.Columns[index];
                header.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
                contentWidth = header.Width;

                header.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
                headerWidth = header.Width;

                if (contentWidth > headerWidth)
                    headerResize = ColumnHeaderAutoResizeStyle.ColumnContent;
                else
                    headerResize = ColumnHeaderAutoResizeStyle.HeaderSize;

                header.AutoResize(headerResize);
            }
        }
    }
}
